package com.inet.app.framework.device;

import java.lang.reflect.Method;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.util.Collections;
import java.util.List;

import org.apache.http.conn.util.InetAddressUtils;

import android.annotation.TargetApi;
import android.app.Activity;
import android.content.Context;
import android.content.res.Configuration;
import android.os.Build;
import android.provider.Settings;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.view.Display;
import android.view.WindowManager;

import com.inet.app.framework.util.SmartLog;

public final class DeviceUtil {

	private final static String MAC_WIRE = "eth0";
	private final static String MAC_WIFI = "wlan0";

	/**
	 * check device is tablet
	 * 
	 * @param context
	 * @return
	 */
	@TargetApi(Build.VERSION_CODES.GINGERBREAD)
	public static boolean isTablet(Context context) {
		boolean xlarge = ((context.getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) == Configuration.SCREENLAYOUT_SIZE_XLARGE);
		boolean large = ((context.getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) == Configuration.SCREENLAYOUT_SIZE_LARGE);
		return (xlarge || large);
	}

	/**
	 * check device is handler normal or small screen
	 * 
	 * @param context
	 * @return
	 */
	public static boolean isNormalOrSmall(Context context) {
		boolean xlarge = ((context.getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) == Configuration.SCREENLAYOUT_SIZE_NORMAL);
		boolean large = ((context.getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) == Configuration.SCREENLAYOUT_SIZE_SMALL);
		return (xlarge || large);
	}

	/**
	 * get device information
	 * 
	 * @param activity
	 * @return
	 */
	@SuppressWarnings("deprecation")
	public static DeviceInfoModel getDeviceInfo(Activity activity) {
		Display display = ((WindowManager) activity
				.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();

		int width = display.getWidth();
		int height = display.getHeight();
		int orientation = getOrientation(activity);
		String serialNumber = getSerialNumber(activity);
		String deviceId = getDeviceId(activity);
		String modelName = getModelName();
		String version = getVersionOS();
		String ipV4 = getIPAddress(true);
		String ipV6 = getIPAddress(false);
		String macAdress = getMACAddress(MAC_WIFI);
		boolean isTablet = isTablet(activity);

		DeviceInfoModel deviceInfo = new DeviceInfoModel();
		deviceInfo.setWidth(width);
		deviceInfo.setHeight(height);
		deviceInfo.setOrientation(orientation);
		deviceInfo.setSerial(serialNumber);
		deviceInfo.setDeviceId(deviceId);
		deviceInfo.setModelName(modelName);
		deviceInfo.setOsVersion(version);
		deviceInfo.setTablet(isTablet);
		deviceInfo.setIpV4(ipV4);
		deviceInfo.setIpV6(ipV6);
		deviceInfo.setMacAdress(macAdress);

		return deviceInfo;
	}

	/**
	 * get orientation of activity
	 * 
	 * @param activity
	 * @return ORIENTATION_LANDSCAPE or ORIENTATION_PORTRAIT
	 */
	public static int getOrientation(Activity activity) {
		Configuration config = activity.getResources().getConfiguration();
		return config.orientation;
	}

	/**
	 * 
	 * @return serial number device
	 */
	public static String getSerialNumber(Context context) {
		try {
			TelephonyManager telephonyManager = (TelephonyManager) context
					.getSystemService(Context.TELEPHONY_SERVICE);
			String imei = telephonyManager.getDeviceId();
			return imei;
		} catch (Exception e) {
			String serialNum;
			try {
				Class<?> classLoader = Class
						.forName("android.os.SystemProperties");
				Method method = classLoader.getMethod("get", String.class,
						String.class);
				serialNum = (String) (method.invoke(classLoader, "ro.serialno"));
			} catch (Exception exception) {
				serialNum = "W80082PE8YA";
			}
			return serialNum;
		}
	}

	/**
	 * The name of the industrial design.
	 * 
	 * @return
	 */
	public static String getDeviceName() {
		return android.os.Build.DEVICE;
	}

	/**
	 * The name of end user
	 * 
	 * @return
	 */
	public static String getModelName() {
		return android.os.Build.MODEL;
	}

	public static String getProductName() {
		return android.os.Build.PRODUCT;
	}

	public static String getVersionOS() {
		return android.os.Build.VERSION.RELEASE;
	}

	/**
	 * Get device ID of each device
	 * 
	 * @param context
	 * @return number device id
	 */
	public static String getDeviceId(Context context) {
		return Settings.Secure.getString(context.getContentResolver(),
				Settings.Secure.ANDROID_ID);
	}

	/**
	 * Returns MAC address of the given interface name.
	 * 
	 * @param interfaceName
	 *            eth0, wlan0 or NULL=use first interface
	 * @return mac address or empty string
	 */
	public static String getMACAddress(String interfaceName) {
		try {
			List<NetworkInterface> interfaces = Collections
					.list(NetworkInterface.getNetworkInterfaces());
			for (NetworkInterface intf : interfaces) {
				if (interfaceName != null) {
					if (!intf.getName().equalsIgnoreCase(interfaceName))
						continue;
				}
				byte[] mac = intf.getHardwareAddress();
				if (mac == null)
					return "";
				StringBuilder buf = new StringBuilder();
				for (int idx = 0; idx < mac.length; idx++)
					buf.append(String.format("%02X:", mac[idx]));
				if (buf.length() > 0)
					buf.deleteCharAt(buf.length() - 1);
				return buf.toString();
			}
		} catch (Exception ex) {
			SmartLog.e(ex.toString());
		}
		return "";
	}

	/**
	 * Get IP address from first non-localhost interface
	 * 
	 * @param ipv4
	 *            true=return ipv4, false=return ipv6
	 * @return address or empty string
	 */
	public static String getIPAddress(boolean useIPv4) {
		try {
			List<NetworkInterface> interfaces = Collections
					.list(NetworkInterface.getNetworkInterfaces());
			for (NetworkInterface intf : interfaces) {
				List<InetAddress> addrs = Collections.list(intf
						.getInetAddresses());
				for (InetAddress addr : addrs) {
					if (!addr.isLoopbackAddress()) {
						String sAddr = addr.getHostAddress().toUpperCase();
						boolean isIPv4 = InetAddressUtils.isIPv4Address(sAddr);
						if (useIPv4) {
							if (isIPv4)
								return sAddr;
						} else {
							if (!isIPv4) {
								int delim = sAddr.indexOf('%'); // drop ip6 port
																// suffix
								return delim < 0 ? sAddr : sAddr.substring(0,
										delim);
							}
						}
					}
				}
			}
		} catch (Exception ex) {
			SmartLog.e(ex.toString());
		}
		return "";
	}
	
	public static String getOperatorName(Context context) {
		String opName = getOperatorNameLocal(context);
		if(TextUtils.isEmpty(opName)) {
			String ipV4 = getIPAddress(true);
			opName = getOperatorNameServer(ipV4);
			if(TextUtils.isEmpty(opName)) {
				opName = getOperatorNameServer();
			}
		}
		return opName;
	}

	public static String getOperatorNameLocal(Context context) {
		TelephonyManager manager = (TelephonyManager) context
				.getSystemService(Context.TELEPHONY_SERVICE);
		String carrierName = manager.getNetworkOperatorName();
		return carrierName;
	}
	
	/**
	 * Make thread use network socket
	 * @param ip
	 * 		ip of device
	 * @return
	 * 		operator name
	 */
	public static String getOperatorNameServer(String ip) {
		//TODO use socket
		return "";
	}
	
	/**
	 * Make thread use network socket
	 * @return
	 * 		operator name
	 */
	public static String getOperatorNameServer() {
		//TODO use socket
		return "";
	}

}
